package com.github.aloxc.plugin.restplus.listener;

import com.github.aloxc.plugin.restplus.common.Consts;
import com.github.aloxc.plugin.restplus.common.RequestHelper;
import com.github.aloxc.plugin.restplus.entity.EnvironmentConfig;
import com.github.aloxc.plugin.restplus.entity.RestConfig;
import com.github.aloxc.plugin.restplus.entity.Setting;
import com.github.aloxc.plugin.restplus.i18n.I18Bundle;
import com.github.aloxc.plugin.restplus.method.HttpMethod;
import com.github.aloxc.plugin.restplus.navigator.RestServiceDetail;
import com.github.aloxc.plugin.restplus.navigator.RestServicesNavigator;
import com.github.aloxc.plugin.restplus.popup.PopupBalloon;
import com.github.aloxc.plugin.restplus.test.RestRequest;
import com.github.aloxc.plugin.restplus.test.RestResponse;
import com.github.aloxc.plugin.restplus.utils.JavaScriptUtil;
import com.github.aloxc.plugin.restplus.utils.StringUtils;
import com.github.aloxc.plugin.restplus.utils.ToolkitUtil;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.ui.awt.RelativePoint;
import org.jetbrains.annotations.NotNull;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 发送请求
 */
public class SendActionListener implements ActionListener {
    private RestServiceDetail restServiceDetail;
    private Editor editor;
    private RelativePoint point;
    private Balloon balloon;

    public SendActionListener(RestServiceDetail restServiceDetail) {
        editor = null;
        this.restServiceDetail = restServiceDetail;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        ProgressManager.getInstance().run(new Task.Backgroundable(null,
                I18Bundle.getMessage("com.github.aloxc.plugin.restplus.request.send.tiptext")) {
            @Override
            public void run(@NotNull ProgressIndicator indicator) {
                final Runnable runnable = () -> {
                    if (StringUtils.isNullOrEmpty(restServiceDetail.getUrl())) {
                        return;
                    }
                    String tempUrl = restServiceDetail.getUrl();
                    RestConfig config = restServiceDetail.getProject().getComponent(RestServicesNavigator.class).getConfig();
                    EnvironmentConfig environmentConfig = null;
                    Map<String, Setting> headerMap = new HashMap(2 << 3);
                    Map<String, Setting> cookieMap = new HashMap(2 << 3);
                    StringBuffer script = new StringBuffer();
                    if (config != null && config.getGlobalConfig().getSettingList() != null) {
                        if (!StringUtils.isNullOrEmpty(config.getGlobalConfig().getTest())) {
                            script.append("\n").append(config.getGlobalConfig().getTest());
                        }
                        config.getGlobalConfig().getSettingList().stream().filter(ele -> ele.isSelected()).forEach(it -> {
                            if (Consts.VariateType.HEADER.getType().equals(it.getType())) {
                                headerMap.put(it.getName(), it);
                            } else if (Consts.VariateType.COOKIE.getType().equals(it.getType())) {
                                cookieMap.put(it.getName(), it);
                            }
                        });
                    }

                    if (config != null && config.getEnv() != null && config.getEnv().size() > 0) {
                        Map<String, EnvironmentConfig> envMap = config.getEnv();
                        for (String envName : envMap.keySet()) {
                            if (envMap.get(envName).isSelected()) {
                                environmentConfig = envMap.get(envName);
                                if (!StringUtils.isNullOrEmpty(environmentConfig.getTest())) {
                                    script.append("\n").append(environmentConfig.getTest());
                                }
                                if (environmentConfig.getSettingList() != null) {
                                    environmentConfig.getSettingList().stream().filter(ele -> ele.isSelected()).forEach(it -> {
                                        if (Consts.VariateType.HEADER.getType().equals(it.getType())) {
                                            headerMap.put(it.getName(), it);
                                        } else if (Consts.VariateType.COOKIE.getType().equals(it.getType())) {
                                            cookieMap.put(it.getName(), it);
                                        }
                                    });
                                }
                            }
                        }
                    }

                    if (config != null && config.getRequestConfig() != null && config.getRequestConfig().size() > 0
                            && config.getRequestConfig().get((restServiceDetail.getParentName() != null ? restServiceDetail.getParentName() + ":" : "") + restServiceDetail.getUrl()) != null) {
                        if (!StringUtils.isNullOrEmpty(config.getRequestConfig().get((restServiceDetail.getParentName() != null ? restServiceDetail.getParentName() + ":" : "") + restServiceDetail.getUrl()).getTest())) {
                            script.append("\n").append(config.getRequestConfig().get((restServiceDetail.getParentName() != null ? restServiceDetail.getParentName() + ":" : "") + restServiceDetail.getUrl()).getTest());
                        }
                        config.getRequestConfig().get((restServiceDetail.getParentName() != null ? restServiceDetail.getParentName() + ":" : "") + restServiceDetail.getUrl()).getSettingList().stream().filter(ele -> ele.isSelected()).forEach(it -> {
                            if (Consts.VariateType.HEADER.getType().equals(it.getType())) {
                                headerMap.put(it.getName(), it);
                            } else if (Consts.VariateType.COOKIE.getType().equals(it.getType())) {
                                cookieMap.put(it.getName(), it);
                            }
                        });
                    }

                    if (restServiceDetail.getRequestParamsTextArea() != null) {
                        String requestParamsText = restServiceDetail.getRequestParamsTextArea().getText();
                        Map<String, Object> paramMap = ToolkitUtil.textToParamMap(requestParamsText);
                        Set<String> usedKeySet = new HashSet<>(2 << 3);
                        if (paramMap != null && paramMap.size() > 0) {
                            // set PathVariable value to request URI
                            String prev = tempUrl;
                            for (String key : paramMap.keySet()) {
                                tempUrl = tempUrl.replaceFirst("\\{(" + key + "[\\s\\S]*?)\\}", String.valueOf(paramMap.get(key)));
                                if (!prev.equals(tempUrl)) {
                                    usedKeySet.add(key);
                                }
                                prev = tempUrl;
                            }
                        }
                        usedKeySet.stream().forEach(k -> paramMap.remove(k));
                        String params = ToolkitUtil.textToRequestParam(paramMap);
                        if (params.length() != 0) {
                            // 包含了参数
                            if (tempUrl.contains("?")) {
                                tempUrl += "&" + params;
                            } else {
                                tempUrl += "?" + params;
                            }
                        }
                    }

                    // 完整url
                    boolean https = environmentConfig.isHttps();
                    String context = environmentConfig.getContext();
                    if (!StringUtils.isNullOrEmpty(context)) {
                        if (!context.startsWith("/")) {
                            context = "/" + context;
                        }
                        if (context.endsWith("/")) {
                            context = context.substring(0, context.length() - 1);
                        }
                    } else {
                        context = "";
                    }
                    tempUrl = (https ? "https://" : "http://") + environmentConfig.getHost() + ":" + environmentConfig.getPort() + context + tempUrl;
                    RestResponse response;
                    if (!StringUtils.isNullOrEmpty(restServiceDetail.getRequestTestTextArea().getText())) {
                        script.append("\n").append(restServiceDetail.getRequestTestTextArea().getText());
                    }
                    RestRequest request = new RestRequest();
                    request.setUrl(tempUrl);
                    request.setHeaderList(headerMap.values());
                    request.setCookieList(cookieMap.values());
                    request.setScript(script.toString());
//                    consoleView.print("开始请求" + tempUrl,type);
                    if ("POST".equals(restServiceDetail.getMethod().toUpperCase())) {
                        if (restServiceDetail.getRequestBodyTextArea() != null
                                && !StringUtils.isNullOrEmpty(restServiceDetail.getRequestBodyTextArea().getText())
                                && !"null".equals(restServiceDetail.getRequestBodyTextArea().getText())) {
                            request.setBody(restServiceDetail.getRequestBodyTextArea().getText());
                            request.setHttpMethod(HttpMethod.POST_BODY);
                        } else {
                            request.setHttpMethod(HttpMethod.getByRequestMethod(restServiceDetail.getMethod()));
                        }
                    } else {
                        request.setHttpMethod(HttpMethod.getByRequestMethod(restServiceDetail.getMethod()));
                    }
                    request.setService(restServiceDetail.getUrl());
                    request.addRequetListener(new RestRequestHistoryListener(restServiceDetail.getParentName()));
                    response = RequestHelper.request(restServiceDetail.getProject(),
                            restServiceDetail.getModule(), restServiceDetail.getUrlTree(), request);
                    if (response != null) {
                        restServiceDetail.setTestIcon(response);
                        restServiceDetail.addResponseTabPanel(response);
                        restServiceDetail.consoleTest(response);


                        if (point != null) {
//                            balloon.hide();
                            //从代码左侧的LineMarker执行的用例
                            PopupBalloon.showPopupBalloon(point, JavaScriptUtil.format(restServiceDetail.getProject(),response.getContent(), 2, ' ') , false);
                        }else if(editor != null){
                            //从代码中直接执行接口的用例
                            PopupBalloon.showPopupBalloon(editor, JavaScriptUtil.format(restServiceDetail.getProject(),response.getContent(), 2, ' ') , false);
                        }
                    }
                };
                runnable.run();
            }
        });
    }

    public void send(Editor editor, RelativePoint point) {
        this.editor = editor;
        this.point = point;
        this.actionPerformed(null);
    }
}
